﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Cityship
{
    class Deck
    {
        public List<Entity> Entities;
        public Tile[,] TileGrid;
        private List<Tile> pressureCheckedTiles;
        public int GetWidth { get { return _width; } }
        public int GetHeight { get { return _height; } }
        private int _width;
        private int _height;
        public Deck(int width, int height)
        {
            _width = width;
            _height = height;
            TileGrid = new Tile[_width, _height];
            pressureCheckedTiles = new List<Tile> { };
            Entities = new List<Entity> { };
        }

        public void PressureCheck()
        {

        }

        public void Clear()
        {
            for (int x = 0; x < _width; x++)
            {
                for (int y = 0; y < _height; y++)
                {
                    Tile currentTile = TileGrid[x, y];

                    if (currentTile.Type != TileType.Nothing)
                    {
                        currentTile.Change(TileType.Floor, "default");
                    }
                }
            }
        }

        public void Outline()
        {
            for (int x = 0; x < this.GetWidth; x++)
            {
                for (int y = 0; y < this.GetHeight; y++)
                {
                    if (LocationHasEmptyNeighbor(x, y))
                    {
                        TileGrid[x, y].Change(TileType.Wall, "default");
                        TileAdjacency.Recalculate(this, x, y);
                    }
                }
            }
        }

        private bool LocationHasEmptyNeighbor(int xPos, int yPos)
        {
            if (TileGrid[xPos, yPos].Type != TileType.Nothing)
            {
                for (int x = xPos - 1; x <= xPos + 1; x++)
                {
                    for (int y = yPos - 1; y <= yPos + 1; y++)
                    {
                        if (x < 0 | x >= this.GetWidth)
                            return true;
                        if (y < 0 | y >= this.GetHeight)
                            return true;

                        if (TileGrid[x, y].Type == TileType.Nothing)
                        {
                            return true;
                        }
                    }

                }
            }
            return false;
        }

        public void EqualizePressure(Vector2 location, int range)
        {
            Point point = new Point((int)(location.X), (int)(location.Y));
            List<Tile> tiles = new List<Tile> { };
            
            float totalPressure = 0f;

            for (int x = point.X - range; x <= point.X + range; x++)
            {
                for (int y = point.Y - range; y <= point.Y + range; y++)
                {
                    if (x < 0 | x >= this.GetWidth)
                        break;
                    if (y < 0 | y >= this.GetHeight)
                        break;

                    Tile tile = TileGrid[x, y];

                    if (tile.Type == TileType.Floor)
                    {
                        if (!pressureCheckedTiles.Contains(tile))
                        {
                            tiles.Add(tile);
                            totalPressure += tile.Pressure;

                            pressureCheckedTiles.Add(tile);
                        }
                    }
                }
            }

            if (tiles.Count > 0)
            {
                foreach (Tile tile in tiles)
                {
                    tile.Pressure = totalPressure / (float)tiles.Count;
                    if (!pressureCheckedTiles.Contains(tile))
                    {
                        EqualizePressure(new Vector2(tile.Location.X, tile.Location.Y), 1);
                    }
                }
            }

            return;
        }

        public void ClearPressureChecked()
        {
            pressureCheckedTiles.Clear();
        }


        public Vector2 ToNearestValidFloorTile(Vector2 location, int range)
        {
            Point point = new Point(Convert.ToInt32(location.X), Convert.ToInt32(location.Y));
            Vector2 nearestPoint = Vector2.Zero;
            Vector2 testPoint = Vector2.Zero;
            for (int x = point.X - range; x <= point.X + range; x++)
            {
                for (int y = point.Y - range; y <= point.Y + range; y++)
                {
                    if (x < 0 | x >= this.GetWidth)
                        break;
                    if (y < 0 | y >= this.GetHeight)
                        break;

                    if (TileGrid[x, y].Type == TileType.Floor)
                    {
                        testPoint = new Vector2(x+0.5f, y+0.5f);
                        if ((testPoint - location).Length() < (nearestPoint - location).Length())
                        {
                            nearestPoint = testPoint;
                        }
                    }
                }
            }

            nearestPoint -= location;

            if (testPoint == Vector2.Zero)
            {
                if (range < 3) //Sanity check, look within * 3 * tiles for valid floors.
                {
                    nearestPoint = ToNearestValidFloorTile(location, range + 1);
                }
                else //There's nothing nearby, flip out.
                {
                    return new Vector2(Utility.rand.Next(-1, 2), Utility.rand.Next(-1, 2))*4;
                }

            }


            return nearestPoint;
        }

        public Vector2 GetCenter() //The pixel center of this deck.
        {
            return new Vector2(_width / 2, _height / 2);
        }

        public void ChangeTileAtPosition(int x, int y, TileType newTileType)
        {
            if (x >= 0 & x < _width && y >= 0 & y < _height && TileGrid[x, y].Type != TileType.Nothing)
            {
                TileGrid[x, y].Change(newTileType, "default");
                TileAdjacency.Recalculate(this, x, y);

                if (newTileType == TileType.Wall)
                {
                    TileGrid[x, y].Pressure = 0f;
                }
            }
        }
    }
}
